﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using CommonVariables = AFS.VisitationRequestTool.Addin.Variables;
using AFS.VisitationRequestTool.Addin.Variables;
using System.Net;

namespace AFS.VisitationRequestTool.Addin.Common
{
    public static class Utility
    {
        // TODO: refactor into smaller classes.
        private static Properties.Settings settings = new Properties.Settings();

        static Utility()
        {

        }

        public static bool IsOrganizer(AppointmentItem appointmentItem)
        {
            if ((appointmentItem.Organizer != null) &&
                (appointmentItem.Session.CurrentUser.Name == appointmentItem.Organizer))
                return true;
            else
                return false;
        }

        public static void LogError(string message, EventLevel eventLevel)
        {
            string source = "AFS.VisitationRequestTool.Addin";
            string log = "Application";

            // TODO: Check permissions to create log
            //if (!EventLog.SourceExists(source))
            //    EventLog.CreateEventSource(source, log);
            Trace.WriteLine(String.Format("Source:{0}, Log:{1}", source, log));
            //EventLog.WriteEntry(source, message, EventLogEntryType.Error, 137);
            // Trace.WriteLine(message.ToString(), eventLevel.ToString());
        }

        public static string GetStringValueFromObject(object objectValue)
        {
            string value = String.Empty;

            if (objectValue != null)
            {
                try
                {
                    value = Convert.ToString(objectValue);
                }
                catch (System.Exception ex)
                {
                    Utility.LogError(ex.ToString(), EventLevel.Error);
                    MessageBox.Show(ErrorMessages.ProgramException);
                }
            }

            return value;
        }

        public static bool GetBooleanValueFromObject(object objectValue)
        {
            bool value = false;

            if (objectValue != null)
            {
                try
                {
                    value = Convert.ToBoolean(objectValue);
                }

                catch (System.Exception ex)
                {
                    Utility.LogError(ex.ToString(), EventLevel.Error);
                    MessageBox.Show(ErrorMessages.ProgramException);
                }
            }

            return value;
        }

        public static string GetInfoPathFormattedDateString(DateTime datetime)
        {
            string value = String.Empty;

            if (datetime != null)
            {
                value = datetime.ToString("yyyy-MM-dd");
            }
            return value;
        }

        public static int GetDateTimeDifference(DateTime startDate, DateTime endDate)
        {
            int dateDifference = 0;

            if (startDate != null && endDate != null)
            {
                TimeSpan timeSpan = endDate - startDate;
                dateDifference = timeSpan.Days;
            }

            return dateDifference;
        }

        public static string GetCalculatedVisitDuration(int durationInMinutes)
        {
            //1440 minutes = 24 hours
            int durationInDays = 1;
            int minutesInDay = 1440;

            if (durationInMinutes > minutesInDay)
            {
                durationInDays = (durationInMinutes / minutesInDay) + 1;
            }
            if (durationInDays > 365)
                throw new System.Exception("Meetings cannot exceed 365 days in duration");

            return durationInDays.ToString();
        }

        public static string GetFrequencyOfVisit(AppointmentItem appointmentItem)
        {
            if (appointmentItem.IsRecurring)
            {
                switch (appointmentItem.GetRecurrencePattern().RecurrenceType.ToString())
                {
                    case "olRecursDaily":
                        return "Daily";
                    case "olRecursWeekly":
                        if (appointmentItem.GetRecurrencePattern().Interval == 2)
                        {
                            return "Bi-Weekly";
                        }
                        else
                        {
                            return "Weekly";
                        }

                    case "olRecursMonthly":
                        if (appointmentItem.GetRecurrencePattern().Interval == 3)
                        {
                            return "Quarterly";
                        }
                        else
                        {
                            return "Monthly";
                        }
                    case "olRecursYearly":
                        return "Yearly";
                    //TODO - Calculate other recurrences Bi Monthly
                    default:
                        return "Other/Undetermined Frequency";
                }

            }
            else
            {
                return "Single";
            }

        }

        public static string GetUserIDFromUserObject(Recipient user)
        {
            return user.AddressEntry.GetExchangeUser().Alias;
        }    

        public static List<string> GetVisitLocationsList(RequestDetailsFormRegion userEntries)
        {
            List<string> visitLocationsList = new List<string>();

            foreach (string visitLocation in userEntries.lstVisitLocations.SelectedItems)
            {
                visitLocationsList.Add(visitLocation);
            }

            return visitLocationsList;
        }

        public static List<string> GetListFromListbox(ListBox lstBox)
        {
            List<string> itemList = new List<string>();

            foreach (string listItem in lstBox.SelectedItems)
            {
                itemList.Add(listItem);
            }

            return itemList;
        }

        public static string[] GetArrayFromListbox(ListBox lstBox)
        {
            string[] itemList = new string[lstBox.SelectedItems.Count];

            for (int i = 0; i < itemList.Length; i++)
            {
                itemList[i] = lstBox.SelectedItems[i].ToString();
            }

            return itemList;
        }

        public static void SaveFileToTemporaryLocation(Attachment attachment, string filePath)
        {

            if (!System.IO.File.Exists(filePath))
            {
                attachment.SaveAsFile(filePath);
            }
        }

        public static void RemoveFileFromTemporaryLocation(string filePath)
        {
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
            }
        }

        public static string GetBase64StringFromFile(string fullFileName)
        {
            string base64EncodedFile = string.Empty;
            byte[] fileArray;
            // This memory stream will hold the InfoPath file attachment buffer before Base64 encoding.
            using (MemoryStream memoryStream = new MemoryStream())
            {

                using (BinaryReader binaryReader = new BinaryReader(System.IO.File.Open(fullFileName, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    string fileName = Path.GetFileName(fullFileName);
                    uint fileNameLength = Convert.ToUInt32(fileName.Length) + 1;
                    byte[] fileNameBytes = Encoding.Unicode.GetBytes(fileName);

                    using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
                    {
                        binaryWriter.Write(new byte[] {
				        0xc7,
				        0x49,
				        0x46,
				        0x41
			        });

                        // Write the default header information.
                        binaryWriter.Write(Convert.ToUInt32(0x14));
                        // size
                        binaryWriter.Write(Convert.ToUInt32(0x1));
                        // version
                        binaryWriter.Write(Convert.ToUInt32(0x0));
                        // reserved
                        // Write the file size.
                        binaryWriter.Write(Convert.ToUInt32(binaryReader.BaseStream.Length));

                        // Write the size of the file name.
                        binaryWriter.Write(Convert.ToUInt32(fileNameLength));

                        // Write the file name (Unicode encoded).
                        binaryWriter.Write(fileNameBytes);

                        // Write the file name terminator. This is two nulls in Unicode.
                        binaryWriter.Write(new byte[] {
				        0,
				        0
			        });

                        // Iterate through the file reading data and writing it to the outbuffer.
                        // TODO: Is ~65K enough capacity for attachments? What if there are embedded images?
                        byte[] data = new byte[64 * 1024];
                        int bytesRead = 1;

                        while (bytesRead > 0)
                        {
                            bytesRead = binaryReader.Read(data, 0, data.Length);
                            binaryWriter.Write(data, 0, bytesRead);
                        }
                    }
                }

                using (MemoryStream memoryStreamOut = new MemoryStream())
                {

                    using (BinaryReader br = new BinaryReader(new MemoryStream(memoryStream.ToArray())))
                    {
                        // Create a Base64 transform to do the encoding.
                        ToBase64Transform base64Transform = new ToBase64Transform();

                        byte[] data = new byte[base64Transform.InputBlockSize];
                        byte[] outData = new byte[base64Transform.OutputBlockSize];

                        int bytesRead = 1;

                        while (bytesRead > 0)
                        {
                            bytesRead = br.Read(data, 0, data.Length);

                            if (bytesRead == data.Length)
                            {
                                base64Transform.TransformBlock(data, 0, bytesRead, outData, 0);
                            }
                            else
                            {
                                outData = base64Transform.TransformFinalBlock(data, 0, bytesRead);
                            }

                            memoryStreamOut.Write(outData, 0, outData.Length);
                        }
                    }
                    //
                    fileArray = memoryStreamOut.ToArray();
                }
            }

            base64EncodedFile = Encoding.ASCII.GetString(fileArray);
            fileArray = null;

            return base64EncodedFile;
        }

        public static System.Net.ICredentials GetCredentials()
        {
            // Check if configured to use default network credentials or service account
            if (!settings.UseServiceAccount) // (!(bool)Properties.Settings.Default["UseServiceAccount"]) 
            {
                return System.Net.CredentialCache.DefaultNetworkCredentials;
            }
            else
            {
                System.Security.SecureString password = new System.Security.SecureString();

                Array.ForEach(settings.Password.ToCharArray(), password.AppendChar);
                return new System.Net.NetworkCredential(settings.Username, password, settings.Domain);
            }
        }
     
    }

    public enum EventLevel
    {
        Info = 1,
        Warning = 2,
        Error = 3,
        Critical = 4
    }
}
